package com.pkk.components.log.aspect;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.pkk.components.log.annotations.Log;
import com.pkk.components.log.config.LoggerUtil;
import com.pkk.components.util.util.IpUtil;

/**
 * @description: 日志切面
 * @author: peikunkun
 * @create: 2018-10-11 10:29
 **/
@Aspect //AOP 切面
@Component
public class LogAspect {

    /**
     * 邮件
     */
    Logger emailLog = LoggerUtil.getEmail("");
    /**
     * 文件日志
     */
    Logger logger   = LoggerUtil.getLogger("", "log");

    /*@Before 前置通知：在某连接点之前执行的通知，但这个通知不能阻止连接点之前的执行流程（除非它抛出一个异常）。
      @Around 环绕通知：可以实现方法执行前后操作，需要在方法内执行point.proceed(); 并返回结果。
      @AfterReturning 后置通知：在某连接点正常完成后执行的通知：例如，一个方法没有抛出任何异常，正常返回。
      @AfterThrowing 异常通知：在方法抛出异常退出时执行的通知。
      @After 后置通知：在某连接点正常完成后执行的通知：例如，一个方法没有抛出任何异常，正常返回。*/

    //切入点
    @Pointcut(value = "@annotation(com.pkk.components.log.annotations.Log)")
    private void pointcut() {
    }


    /**
     * 在方法执行前后
     *
     * @param point
     * @param log
     * @return
     */
    @Around(value = "pointcut() && @annotation(log)")
    public Object around(ProceedingJoinPoint point, Log log) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //拦截的类名
        Class clazz = point.getTarget().getClass();
        //拦截的方法
        Method method = ((MethodSignature) point.getSignature()).getMethod();
        //请求时间
        final String requestTime = new SimpleDateFormat().format(new Date());
        //请求接口
        final String requestUrl = log.requestUrl();
        //请求接口描述
        final String desc = log.desc();
        //访问用户
        final String user = log.user();
        //是否发送邮件
        final boolean sendEmail = log.isSendEmail();
        //发送的邮件备注信息
        final String emailRemake = log.emailRemake();
        //请求的ip地址
        final String[] ipAddresses = IpUtil.getIpAddresses(request);

        StringBuffer logBuffer = new StringBuffer("日志信息:");

        if (StringUtils.isNotBlank(user)) {
            logBuffer.append("访问用户:{");
            logBuffer.append(user);
            logBuffer.append("} - ");
        }

        if (StringUtils.isNotBlank(requestTime)) {
            logBuffer.append("请求时间:{");
            logBuffer.append(requestTime);
            logBuffer.append("} - ");
        }

        if (StringUtils.isNotBlank(requestTime)) {
            logBuffer.append("请求地址:{");
            logBuffer.append(requestUrl);
            logBuffer.append("} - ");
        }

        if (null != ipAddresses && ipAddresses.length >= 1) {
            logBuffer.append("访问人ip:{");
            logBuffer.append(Arrays.toString(ipAddresses));
            logBuffer.append("} - ");
        }

        if (StringUtils.isNotBlank(desc)) {
            logBuffer.append("接口描述:{");
            logBuffer.append(desc);
            logBuffer.append("} - ");
        }


        if (sendEmail) {
            if (StringUtils.isNotBlank(emailRemake)) {
                logBuffer.append("备注:{");
                logBuffer.append(emailRemake);
                logBuffer.append("} - ");
            }
            emailLog.error(logBuffer.toString());
        } else {
            logger.info(logBuffer.toString());
        }
        try {
            return point.proceed(); //执行程序
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            return throwable.getMessage();
        }
    }

    public void makeLog() {

    }


    /**
     * 方法执行后
     *
     * @param joinPoint
     * @param log
     * @param result
     * @return
     */
    @AfterReturning(value = "pointcut() && @annotation(log)", returning = "result")
    public Object afterReturning(JoinPoint joinPoint, Log log, Object result) {
//        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//        HttpSession session = request.getSession();
        return result;
    }

    /**
     * 方法执行后 并抛出异常
     *
     * @param joinPoint
     * @param log
     * @param ex
     */
    @AfterThrowing(value = "pointcut() && @annotation(log)", throwing = "ex")
    public void afterThrowing(JoinPoint joinPoint, Log log, Exception ex) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //请求时间
        final String requestTime = new SimpleDateFormat().format(new Date());
        //请求接口
        final String requestUrl = log.requestUrl();
        //请求接口描述
        final String desc = log.desc();
        //访问用户
        final String user = log.user();
        //是否发送邮件
        final boolean sendEmail = log.isSendEmail();
        //发送的邮件备注信息
        final String emailRemake = log.emailRemake();
        //请求的ip地址
        final String[] ipAddresses = IpUtil.getIpAddresses(request);

        StringBuffer logBuffer = new StringBuffer("日志信息:");

        if (StringUtils.isNotBlank(user)) {
            logBuffer.append("访问用户:{");
            logBuffer.append(user);
            logBuffer.append("} - ");
        }

        if (StringUtils.isNotBlank(requestTime)) {
            logBuffer.append("请求时间:{");
            logBuffer.append(requestTime);
            logBuffer.append("} - ");
        }

        if (StringUtils.isNotBlank(requestTime)) {
            logBuffer.append("请求地址:{");
            logBuffer.append(requestUrl);
            logBuffer.append("} - ");
        }

        if (null != ipAddresses && ipAddresses.length >= 1) {
            logBuffer.append("访问人ip:{");
            logBuffer.append(Arrays.toString(ipAddresses));
            logBuffer.append("} - ");
        }

        if (StringUtils.isNotBlank(desc)) {
            logBuffer.append("接口描述:{");
            logBuffer.append(desc);
            logBuffer.append("} - ");
        }


        logBuffer.append("异常信息\br:{");
        logBuffer.append(ex.getStackTrace());
        logBuffer.append("} - ");
        emailLog.error(logBuffer.toString());

    }

}
